﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace MetaSharp.Transformation.Patterns
{
    class ObjectPattern : Pattern
    {
        public IEnumerable<PropertyPattern> Properties { get; private set; }
        public Type Type;

        public ObjectPattern(Type type, PropertyPattern[] properties)
            : base(PatternKind.Object)
        {
            this.Type = type;
            this.Properties = properties;
        }

        public override PatternMatch Compile()
        {
            var properties = new List<PropertyPatternMatch>();
            foreach (var property in Properties)
                properties.Add(property.Compile());

            return s => Target(s, Type, properties);
        }

        private static async Task<IMatch> Target(IScope scope, Type type, IList<PropertyPatternMatch> properties)
        {
            if (!scope.Stream.IsEmpty)
            {
                var next = scope.Stream.Next();
                if (next.Current != null && type.IsAssignableFrom(next.Current.GetType()))
                {
                    IMatch match = new Match(
                        next.Current,
                        scope,
                        scope.SetStream(next));

                    var propScope = scope.SetStream(next);
                    foreach (var property in properties)
                    {
                        var propMatch = await property(
                            propScope,
                            next.Current);

                        if (!propMatch.Matched)
                            return await Transformation.Match.Fail(scope);

                        match = match
                            .AddErrors(propMatch.Errors)
                            .AddVariables(propMatch.End.Variables);
                    }

                    return match;
                }
            }

            return await Transformation.Match.Fail(scope);
        }
    }
}
